﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;

namespace ICSharpCode.WinFormsUI.Controls
{
    public class NComboBox : System.Windows.Forms.ComboBox
    {
        private int _itemHeight = 18;
        public new int ItemHeight
        {
            get { return _itemHeight; }
            set { _itemHeight = value; }
        }

        private Image _itemIcon = null;
        public Image ItemIcon
        {
            get { return _itemIcon; }
            set { _itemIcon = value; }
        }

        private Color _backColor = SystemColors.Window;
        private Color _foreColor = SystemColors.ControlText;
        private Color _borderColor = SystemColors.ControlDark;

        public new Color BackColor
        {
            get { return _backColor; }
            set
            {
                _backColor = value;
                base.BackColor = _backColor;
            }
        }

        public new Color ForeColor
        {
            get { return _foreColor; }
            set
            {
                _foreColor = value;
                base.ForeColor = _foreColor;
            }
        }

        public Color BorderColor
        {
            get { return _borderColor; }
            set { _borderColor = value; }
        }

        int WM_PAINT = 0xf; //要求一个窗口重画自己,即Paint事件时 

        //返回hWnd参数所指定的窗口的设备环境。
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        static extern IntPtr GetWindowDC(IntPtr hWnd);

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        //函数释放设备上下文环境（DC）  
        static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);            

        public NComboBox()
        {
            //this.DoubleBuffered = true;           
            this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
            this.Font = new System.Drawing.Font(this.Font.FontFamily, 9.0f);
            this.DrawMode = DrawMode.OwnerDrawFixed;
            this.DropDownStyle = ComboBoxStyle.DropDownList;
            this.UpdateStyles();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            if (m.Msg == WM_PAINT)
            {
                IntPtr hDC = GetWindowDC(m.HWnd);
                if (hDC.ToInt32() == 0) //如果取设备上下文失败则返回     
                {
                    return;
                }
                PaintComboBox(Graphics.FromHdc(hDC));
                ReleaseDC(m.HWnd, hDC);
            }
        }

        private void PaintComboBox(Graphics g)
        {
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;

            int iDropDownButtonWidth = 20;
            int iDropDownButtonHeight = this.Height;

            int iDropDownButtonLocatinX = 20;
            int iDropDownButtonLocatinY = 0;
            
            //下拉按钮
            Rectangle dropDownRectangle = new Rectangle(ClientRectangle.Width - iDropDownButtonLocatinX, iDropDownButtonLocatinY, iDropDownButtonWidth, iDropDownButtonHeight);

            //背景色刷
            Brush bkgBrush = new SolidBrush(_backColor);

            //字体色刷
            Brush fcBrush = new SolidBrush(_foreColor);           

            int iBackColorX = 0;
            //为了字体正常，Enable时只是重画按钮区域
            if (this.Enabled)
            {
                iBackColorX = this.Width - 20;
            }            

            string selectedText = this.Text;
            if (!Enabled)
            {               
                fcBrush = new SolidBrush(Color.FromArgb(200, _foreColor));
            }

            //画背景
            g.FillRectangle(bkgBrush, iBackColorX, 0, ClientRectangle.Width, ClientRectangle.Height);

            //画文本
            //g.DrawString(selectedText, this.Font, fcBrush, new Rectangle(new Point(4, 2), new Size(this.Width - iDropDownButtonWidth - 8, this.Height - 4)), new StringFormat() { LineAlignment = StringAlignment.Center });
            TextRenderer.DrawText(g, selectedText,this.Font, new Rectangle(new Point(4, 2), new Size(this.Width - iDropDownButtonWidth - 8, this.Height - 4)), ((SolidBrush)fcBrush).Color, TextFormatFlags.SingleLine | TextFormatFlags.VerticalCenter | TextFormatFlags.WordEllipsis);

            //画边框           
            ControlPaint.DrawBorder(g, new Rectangle(0, 0, this.Width, this.Height), _borderColor, ButtonBorderStyle.Solid);

            //画下拉按钮
            ComboBoxRenderer.DrawDropDownButton(g, dropDownRectangle, this.Enabled ? ComboBoxState.Normal : ComboBoxState.Disabled);

            g.Dispose();

            bkgBrush.Dispose();
            fcBrush.Dispose();

        }

        protected override void OnMeasureItem(MeasureItemEventArgs e)
        {
            base.OnMeasureItem(e);
            e.ItemHeight = _itemHeight;
        }

        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            //获取要在其上绘制项的图形表面
            Graphics g = e.Graphics;           
            System.Drawing.Rectangle rect = e.Bounds;

            Brush itemBrush = null;
            Color itemTextForeColor = Color.Transparent;

            if (e.Index <= -1)
                return;

            if (e.State == DrawItemState.None ||
                    e.State == (DrawItemState.NoAccelerator | DrawItemState.NoFocusRect))
            {
                itemBrush = new SolidBrush(_backColor);
                itemTextForeColor = _foreColor;
            }
            else if (e.State == DrawItemState.Selected ||
                e.State == DrawItemState.Focus ||
                e.State == (DrawItemState.Selected | DrawItemState.NoAccelerator | DrawItemState.NoFocusRect)||
                e.State == (DrawItemState.Selected | DrawItemState.Focus | DrawItemState.NoAccelerator | DrawItemState.NoFocusRect) ||
                e.State == (DrawItemState.Selected | DrawItemState.Focus | DrawItemState.NoAccelerator | DrawItemState.NoFocusRect | DrawItemState.ComboBoxEdit))
            {
                itemBrush = new SolidBrush(SystemColors.Highlight);
                itemTextForeColor = Color.White;
            }
            else
            {
                itemBrush = new SolidBrush(_backColor);
                itemTextForeColor = _foreColor;
            }
            g.FillRectangle(itemBrush, rect);
            int drawTextPosX = rect.Left;
            int drawTextPosY = rect.Top;
            Rectangle itemTextRect = new Rectangle(drawTextPosX, drawTextPosY, rect.Width, rect.Height);
            if (_itemIcon != null)
            {
                drawTextPosX += _itemIcon.Size.Width + 4;
                itemTextRect = new Rectangle(drawTextPosX, drawTextPosY, rect.Width - _itemIcon.Size.Width - 8, rect.Height);
                g.DrawImage(_itemIcon, new Point(rect.Left + 2, rect.Top + (rect.Height - _itemIcon.Height) / 2));
            }
            string itemText = Items[e.Index].ToString();
            TextRenderer.DrawText(g, itemText, this.Font, itemTextRect, itemTextForeColor, TextFormatFlags.SingleLine | TextFormatFlags.VerticalCenter | TextFormatFlags.WordEllipsis);
            e.DrawFocusRectangle();

        }

    }
}
